#include "semaphores.h"
#include "process.h"
#include "os_io.h"

/*
* > Spawn 3 processes with priority high, low, lowest
* > lowest process:
* > > lock sem 1 => success
* > > trylock sem 2 => success
* > > trylock sem 1 => fail
* > > spawn low process => gets blocked
*
* > low process:
* > > trylock sem 1 => fail
* > > lock sem 1 => blocked
*
* > lowest_process:
* > > spawn high process => gets blocked
*
* > high process:
* > lock sem 1 => blocked
*
* > lowest process: 
* > unlock sem 1 => blocked
*
* > low process:
* > unlock sem 1 => blocked
*
* > high process:
* > unlock sem 1
* > exit
*
* > low process:
* > exit

* > lowest process:
* > unlock sem 2
* > exit
*/

static sem_t *sem1;
static sem_t *sem2;
static int counter = 0;


void high_sem(void)
{
   err_t err_code;

   printf("0xD. High process started: 0x%x\n", counter++);
   err_code = sem_trylock(sem1);
   printf("0xE. High process sem1 trylock status: 0x%x, err_code:0x%x\n", counter++, err_code);

   printf("0xF. High process trying to lock sem1: 0x%x\n", counter++);
   err_code = sem_lock(sem1);
   printf("0xK. High process resume after lock sem1. 0x%x, err_code = 0x%x\n", counter++, err_code);

   printf("0xL, High process unlocking sem1\n");
   err_code = sem_unlock(sem1);
   printf("0xM. High process resume after unlock sem1. 0x%x, err_code = 0x%x\n", counter++, err_code);

   printf("0xN. High process exiting\n");
   return;
}


void low_sem(void)
{
   err_t err_code;

   printf("0x8. Low process started: 0x%x\n", counter++);
   err_code = sem_trylock(sem1);
   printf("0x9. Low process sem1 trylock status: 0x%x, err_code:0x%x\n", counter++, err_code);

   printf("0xA. Low process trying to lock sem1: 0x%x\n", counter++);
   err_code = sem_lock(sem1);
   printf("0xI. Low process resume after lock sem1. 0x%x, err_code = 0x%x\n", counter++, err_code);

   printf("0xJ, Low process unlocking sem1\n");
   err_code = sem_unlock(sem1);
   printf("0xO. Low process resume after unlock sem1. 0x%x, err_code = 0x%x\n", counter++, err_code);

   printf("0xP. Low process exiting\n");
   return;
}

   
void lowest_sem(void)
{
    err_t err_code;

    printf("0x1. Started lowest process, 0x%x\n", counter++);

    err_code = sem_create(&sem1);
    printf("0x2. Sem1 create status: 0x%x, error_code:0x%x\n", counter++, err_code);
    if (err_code != ERR_SUCCESS) { return; }

    err_code = sem_create(&sem2);
    printf("0x3. Sem2 create status: 0x%x, err:0x%x\n", counter++, err_code);
    if (err_code != ERR_SUCCESS) { 
        sem_release(sem1);
	return;
    }

    err_code = sem_lock(sem1);
    printf("0x4. Sem1 lock status: 0x%x, err:0x%x\n", counter++, err_code);
    if (err_code != ERR_SUCCESS) { 
        sem_release(sem1);
	sem_release(sem2);
	return;
    }

    err_code = sem_trylock(sem2);
    printf("0x5. Sem2 trylock status: 0x%x, err:0x%x\n", counter++, err_code);
    if (err_code != ERR_SUCCESS) {
        sem_release(sem1);
	sem_release(sem2);
	return;
    }

    err_code = sem_trylock(sem1);
    printf("0x6. Sem1 trylock status: 0x%x, err:0x%x\n", counter++, err_code);
    if (err_code != ERR_BUSY) {
        sem_release(sem1);
	sem_release(sem2);
	return;
    }

    printf("0x7. Spawning low process, 0x%x\n", counter++);
    exec_mem(low_sem, (const uint8_t *)"low_sem", 0, 9);
    printf("0xB. Lowest process resuming, 0x%x\n", counter++);

    printf("0xC. Spawning high process, 0x%x\n", counter++);
    exec_mem(high_sem, (const uint8_t *)"high sem", 0, 8);
    printf("0xG. Lowest process resuming, 0x%x\n", counter++);

    printf("0xH. Lowest process: unlocking sem1, 0x%x\n", counter++);
    err_code = sem_unlock(sem1);
    printf("0xQ. Lowest process: continuing after unlock. 0x%x, err_code:0x%x\n", counter++, err_code);

    printf("0xR. Lowest process: unlocking sem2, 0x%x\n", counter++);
    err_code = sem_unlock(sem2);
    printf("0xS. Lowest process continuing after unlock. 0x%x, err_code:0x%x\n", counter++, err_code);

    err_code = sem_release(sem1);
    printf("0xT: Sem1 released. 0x%x, err_code: 0x%x", counter++, err_code);
    err_code = sem_release(sem2);
    printf("0xU: Sem2 released. 0x%x, err_code: 0x%x\n", counter++, err_code);

    printf("0xV: Lowest process exiting, 0x%x\n", counter++);
    return;
}

void test_semaphores(void)
{
    printf("Starting to test semaphores\n");
    exec_mem(lowest_sem, (const uint8_t *)"lowest sem", 0, 10);
    return;
}












